# Set PowerShell output encoding to UTF-8
$OutputEncoding = New-Object -typename System.Text.UTF8Encoding

# Function to handle errors
function Handle-Error {
    param ([string]$message)
    Write-Host $message -ForegroundColor Red  # Error messages in Red
    exit 1
}

# Function to check and pull the required image if not found locally
function Check-And-Pull-Image {
    param (
        [string]$imageName,  # Image name (e.g., openjdk:17-jdk-slim)
        [string]$localName   # Local name to check (e.g., openjdk)
    )
    
    $imageExists = docker images --format "{{.Repository}}" | Select-String -Pattern "^$localName$"
    if (-not $imageExists) {
        Write-Host "$localName image not found locally. Pulling $imageName..." -ForegroundColor Cyan  # Informational messages in Cyan
        docker pull $imageName
        if ($LASTEXITCODE -ne 0) {
            Handle-Error "Failed to pull $imageName. Please check your Docker setup."
        }
    } else {
        Write-Host "$localName image found locally. Skipping pull." -ForegroundColor Green  # Success messages in Green
    }
}

# Function to tag a specific image
function Tag-Image {
    param (
        [string]$serviceName,         # The service name (backend, frontend, etc.)
        [string]$repository,          # The Docker repository
        [string]$tag                  # The image tag (e.g., latest or timestamp)
    )
    
    $imageTag = "${repository}-${serviceName}:${tag}"  # Tag with chosen tag
    
    Write-Host "Tagging $imageTag..." -ForegroundColor Cyan
    docker tag $imageTag "${repository}-${serviceName}:${tag}"
    if ($LASTEXITCODE -ne 0) {
        Handle-Error "Failed to tag image ${repository}-${serviceName}:${tag}."
    }
}

# Function to push a specific image
function Push-Image {
    param (
        [string]$serviceName,         # The service name (backend, frontend, etc.)
        [string]$repository,          # The Docker repository
        [string]$tag                  # The image tag (e.g., latest or timestamp)
    )
    
    $imageFullName = "${repository}-${serviceName}:${tag}"
    
    Write-Host "Pushing $imageFullName to Docker repository..." -ForegroundColor Cyan
    docker push $imageFullName
    if ($LASTEXITCODE -ne 0) {
        Handle-Error "Failed to push image $imageFullName."
    }
}

# Function to prompt the user for a yes/no choice
function Prompt-YesNo {
    param (
        [string]$message
    )
    while ($true) {
        $choice = Read-Host "$message (y/n)"
        if ($choice -match '^[Yy]$') {
            return $true
        } elseif ($choice -match '^[Nn]$') {
            return $false
        } else {
            Write-Host "Invalid input. Please enter 'y' or 'n'." -ForegroundColor Yellow
        }
    }
}

# Check if Docker daemon is running
try {
    docker info > $null
} catch {
    Handle-Error "Docker does not seem to be running. Please start Docker and try again."
}

# Docker Desktop automatically uses the credentials stored on the system, no need for explicit login

# Prompt user to select tagging method
Write-Host "Select Tagging Method:" -ForegroundColor Yellow
Write-Host "1. Tag all images as 'latest'"
Write-Host "2. Tag all images with the current timestamp"
$tagOption = Read-Host "Enter your choice (1 or 2)"

switch ($tagOption) {
    '1' {
        $tag = "latest"
        Write-Host "Selected tagging method: 'latest'" -ForegroundColor Green
    }
    '2' {
        $tag = (Get-Date -Format "yyyyMMdd-HHmmss")
        Write-Host "Selected tagging method: Timestamp ($tag)" -ForegroundColor Green
    }
    default {
        Handle-Error "Invalid selection. Please run the script again and choose either 1 or 2."
    }
}

# Prompt user to decide whether to ignore cache during build
$ignoreCache = $false
$ignoreCacheChoice = Prompt-YesNo "Do you want to ignore Docker cache and force rebuild images?"
if ($ignoreCacheChoice) {
    $ignoreCache = $true
    Write-Host "Selected to ignore cache during build." -ForegroundColor Green
} else {
    Write-Host "Selected to use Docker cache during build." -ForegroundColor Green
}

# Define repository
$repository = "jerrylee1215/studentmindhub"  # Change this to your Docker repository address

# Set environment variables for docker-compose
$env:REPOSITORY = $repository
$env:TAG = $tag

# Check and pull necessary base images if not present locally
Check-And-Pull-Image -imageName "openjdk:17-jdk-slim" -localName "openjdk"
Check-And-Pull-Image -imageName "node:16" -localName "node"
Check-And-Pull-Image -imageName "nginx:alpine" -localName "nginx"

# Display the build command
Write-Host "Executing docker-compose build with the following options:" -ForegroundColor Yellow
if ($ignoreCache) {
    Write-Host "  - Using --no-cache option to force rebuild (ignoring cache)." -ForegroundColor Yellow
} else {
    Write-Host "  - Using Docker cache during build." -ForegroundColor Yellow
}

# Build Docker images using docker-compose
Write-Host "Building images with docker-compose..." -ForegroundColor Cyan
$buildCommand = "docker-compose build"
if ($ignoreCache) {
    $buildCommand += " --no-cache"
}

Write-Host "Running command: $buildCommand" -ForegroundColor Cyan

try {
    Invoke-Expression $buildCommand
    if ($LASTEXITCODE -ne 0) {
        Handle-Error "Failed to build images with docker-compose."
    }
} catch {
    Handle-Error "Failed to build images with docker-compose."
}

# List of services to build and tag (backend, frontend-teacher, frontend-student, frontend-school)
$services = @("backend", "frontend-teacher", "frontend-student", "frontend-school")

# Loop through each service and tag it
foreach ($service in $services) {
    Tag-Image -serviceName $service -repository $repository -tag $tag
}

Write-Host "All images have been successfully built and tagged as '$tag'." -ForegroundColor Green

# Prompt user to decide whether to push the images
$pushChoice = Prompt-YesNo "Do you want to push the tagged images to the Docker repository?"

if ($pushChoice) {
    foreach ($service in $services) {
        Push-Image -serviceName $service -repository $repository -tag $tag
    }
    Write-Host "All images have been successfully pushed to the Docker repository." -ForegroundColor Green
} else {
    Write-Host "Skipping push to Docker repository. You can push the images later using 'docker push'." -ForegroundColor Yellow
}
